package routinepackage

import (
	"fmt"
	"time"
)

func test1LongSleep() {
	fmt.Println("begin to long sleep")
	time.Sleep(5 * time.Second)
	fmt.Println("end to long sleep")
}

func test1ShortSleep() {
	fmt.Println("begin to short sleep")
	time.Sleep(2 * time.Second)
	fmt.Println("end to short sleep")
}

func test1() {
	fmt.Println("begin to test1")
	go test1LongSleep()
	go test1ShortSleep()
	fmt.Println("sleep in test1")
	time.Sleep(10 * time.Second)
	fmt.Println("end to test1")
}

func test2sendData(ch chan string) {
	ch <- "hello go"
	ch <- "hi cpp"

	ch <- "this is channel"
}
func test2getData(ch chan string) {
	for {
		input := <-ch
		fmt.Println(input)
	}
}

func test2() {
	ch := make(chan string)
	go test2sendData(ch)
	go test2getData(ch)

	time.Sleep(1 * time.Second)
}

func test3sendData(ch chan int) {
	for i := 0; ; {
		ch <- i
		fmt.Println("send number:", i)
	}
}

func test3() {
	ch := make(chan int)
	go test3sendData(ch)
	fmt.Println(<-ch)
	time.Sleep(3 * time.Second)
}

func test4Pump(ch chan int) {
	for i := 0; ; i++ {
		ch <- i
	}
}

func test4Suck(ch chan int) {
	for {
		fmt.Println(<-ch)
	}
}

func test4() {
	ch := make(chan int)
	go test4Pump(ch)
	go test4Suck(ch)
	time.Sleep(1 * time.Second)
}

type test5Empty interface {
}

type test5Semaphore chan test5Empty

// P 对于信号量做申请
func (s test5Semaphore) P(n int) {
	// 新建一个资源，将它塞到信号量s当中
	e := new(test5Empty)
	for i := 0; i < n; i++ {
		s <- e
	}
}

// V 对于信号量做释放
func (s test5Semaphore) V(n int) {
	// 从s中读取对应的数据
	for i := 0; i < n; i++ {
		<-s
	}
}

// Lock 对资源做申请
func (s test5Semaphore) Lock() {
	s.P(1)
}

// Unlock 对资源做释放
func (s test5Semaphore) Unlock() {
	s.V(1)
}

// Wait 要从信号量中申请n个数据，必须得有n个空位才能塞的进去，否则不能成功
func (s test5Semaphore) Wait(n int) {
	s.P(n)
}

// Signal 从信号量中提取数据
func (s test5Semaphore) Signal() {
	s.V(1)
}

func pump() chan int {
	ch := make(chan int)
	go func() {
		for i := 0; ; i++ {
			time.Sleep(1e9)
			ch <- i
		}
	}()
	return ch
}

func test5() {
	stream := pump()
	for v := range stream {
		fmt.Println(v)
	}
}

func test6f1(ch chan int) {
	for i := 0; ; i++ {
		ch <- i
	}
}

// 一直从通道中读取消息
func test6f2(ch chan int) {
	for {
		fmt.Println(<-ch)
		time.Sleep(1 * time.Second)
	}
}

// 创建一个通道，5s后关闭
func test6Func1(ch chan int) {
	defer close(ch)
	go test6f1(ch)
	go test6f2(ch)
	time.Sleep(5 * time.Second)
}

func test6() {
	ch := make(chan int)
	test6Func1(ch)
	v, ok := <-ch
	fmt.Println(v, ok)
}

// 向信道中塞入数据
func test7Pump1(ch chan int) {
	for i := 0; ; i++ {
		ch <- i
	}
}

// 向信道中塞入数据
func test7Pump2(ch chan int) {
	for i := 0; ; i++ {
		ch <- i
	}
}

// 从信道中取数据
func test7Suck(ch1, ch2 chan int) {
	for {
		select {
		case m := <-ch1:
			fmt.Println("get from channel1: ", m)
		case n := <-ch2:
			fmt.Println("get from channel2: ", n)
		}
	}
}

func test7() {
	ch1 := make(chan int)
	ch2 := make(chan int)

	go test7Pump1(ch1)
	go test7Pump2(ch2)
	go test7Suck(ch1, ch2)

	time.Sleep(1 * time.Second)
}

type test8Req struct {
	a, b  int
	reply chan int
}

type binOp func(a, b int) int

func test8Run(op binOp, req *test8Req) {
	req.reply <- op(req.a, req.b)
}

func server(op binOp, service chan *test8Req) {
	for {
		req := <-service
		go test8Run(op, req)
	}
}

func startServer(op binOp) chan *test8Req {
	req := make(chan *test8Req)
	go server(op, req)
	return req
}

func test8() {
	// 获取一个加法服务器的信道
	addr := startServer(func(a, b int) int { return a + b })

	// 模拟请求的到来
	var reqs [100]test8Req
	for i := 0; i < 100; i++ {
		req := &reqs[i]
		req.a = i
		req.b = 10
		req.reply = make(chan int)
		addr <- req
	}
}

func Test() {
	test7()
}
